import multiprocessing
import os
import sys
from time import sleep
from logging import INFO
import signal
from datetime import datetime
import setproctitle
VN_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
if VN_ROOT not in sys.path:
    sys.path.append(VN_ROOT)
from vn_local.event import EventEngine
from vn_local.trader.engine import MainEngine
from vn_local.gateway.barbican import BBCGateway
from vn_local.trader.setting import SETTINGS
from vn_local.trader.utility import load_json
from vn_local.app.market_maker import CtaStrategyApp
from vn_local.app.market_maker.base import EVENT_CTA_LOG
from vn_local.trader.logger_util import MainLog
import json

SETTINGS["log.active"] = True
SETTINGS["log.level"] = INFO
SETTINGS["log.console"] = True
SETTINGS["log.file"] = True

STARTED = False
TERMINATE = False
gracefully_shutdown_fail = False
parent_pid: int = 0
child_pid: int = 0
coin_name = str(os.getcwd()).split('/')[-1].lower()


def run_child():
    global child_pid, gracefully_shutdown_fail, STARTED, TERMINATE
    child_pid = os.getpid()
    proc_title = f"{coin_name}-child"
    setproctitle.setproctitle(proc_title)
    # print(f"{proc_title}进程开始, 进程号{child_pid}")
    MainLog.info(f"{proc_title}进程开始, 进程号{child_pid}")

    # 创建事件引擎
    event_engine = EventEngine()
    # 创建主引擎
    main_engine = MainEngine(event_engine)
    # 添加gateway
    main_engine.add_gateway(BBCGateway)
    # 添加策略app
    cta_engine = main_engine.add_app(CtaStrategyApp)
    # 启动策略app线程
    cta_engine.init_engine()
    # 主引擎创建成功
    main_engine.write_log("主引擎创建成功")
    # 注册日志事件
    log_engine = main_engine.get_engine("log")
    event_engine.register(EVENT_CTA_LOG, log_engine.process_log_event)
    main_engine.write_log("注册日志事件监听")

    # 连接、启动bbc线程
    connect_bbc_setting = load_json("connect_bbc.json")
    main_engine.connect(connect_bbc_setting, 'BBC')
    main_engine.write_log("连接BBC接口")
    # # 连接状态检查

    main_engine.write_log("连接成功")

    sleep(4)
    cta_engine.init_all_strategies()
    # cta_engine.init_strategy("mm_btse")
    sleep(4)
    cta_engine.start_all_strategies()
    # cta_engine.init_strategy("mm_btse")
    STARTED = True

    def ctrl_handler(signum, frame):
        global TERMINATE, gracefully_shutdown_fail
        MainLog.info('接管进程信号')
        # spread_engine.stop()
        cta_engine.stop_all_strategies()
        # print("做市引擎关闭")
        MainLog.info('做市引擎关闭')
        TERMINATE = True
        i = 0
        while not cta_engine.if_stop_finished():
            i += 1
            if i >= 100:
                main_engine.send_dingding(f"{coin_name}:安全退出超过1分钟，请检查")
                MainLog.info(f"{coin_name}:安全退出超过1分钟，请检查")
                gracefully_shutdown_fail = True
                break
            sleep(0.1)

        if gracefully_shutdown_fail:
            MainLog.info("gracefully shutdown fail, cancel all")
            # cta_engine.cancel_all_orders("LTC-USDT.BTSE")
            cta_engine.main_engine.close()
        else:
            MainLog.info("gracefully shutdown success")
            cta_engine.main_engine.close()

        # spread_engine.strategy_engine.stop_all_strategies()

    signal.signal(signal.SIGINT, ctrl_handler)  # 接管ctrl_c
    signal.signal(signal.SIGTERM, ctrl_handler)  # 接管kill -15


def run_parent():
    global child_pid, parent_pid, STARTED, TERMINATE
    proc_title = f"{coin_name}-parent"
    setproctitle.setproctitle(proc_title)
    parent_pid = os.getpid()
    print(f"{proc_title}进程开始, 进程号{parent_pid}")

    child_process = None
    try:
        while True:

            if not STARTED and not TERMINATE and not child_process:
                child_process = multiprocessing.Process(target=run_child)
                child_process.start()
                child_pid = child_process.pid

            if TERMINATE and child_process is not None:
                if child_process.is_alive():
                    os.kill(child_pid, signal.SIGTERM)
                    child_process.join(100)

                child_process = None

            sleep(1)

    except KeyboardInterrupt:
        print('手动干预, 关闭守护父进程')
        sys.exit()


if __name__ == '__main__':
    run_parent()